import java.util.ArrayList;
import java.util.List;

/*
    生产者和消费者均衡
    1、使用wait方法和notify方法实现“生产者和消费者模式”
    2、什么是“生产者和消费者模式”？
        生产线程负责生产，消费线程负责消费
        生产线程和消费线程要达倒均衡
    3、wait方法和notify方法不是线程对象的方法，是普通对象都有的方法
    4、wait方法和notify方法建立在线程同步基础之上。因为多线程要同时操控一个库，有线程安全问题
    5、wait方法作用：o.wait()让正在o对象上活动的线程t进入等待状态，并且释放掉t线程之前占领o对象的锁
    6、notify方法作用：o.notify()让正在o对象上等待的线程唤醒，只是通知，不会释放o对象上之前占有的锁
 */
public class ThreadTest05 {
    public static void main(String[] args) {
        List list = new ArrayList();
        Thread t1 = new Thread(new Produce(list));
        Thread t2 = new Thread(new Customer(list));

        t1.setName("生产者线程");
        t2.setName("消费者线程");

        t1.start();
        t2.start();
    }
}
//生产线程
class Produce implements Runnable{
    //仓库
    private List list;
    public Produce(List list){
        this.list = list;
    }
    @Override
    public void run() {
        //一直生产
        while (true){
            //给仓库对象list枷锁
            synchronized (list){
                if(list.size() > 0){ //大于0，说明仓库中已经有一个元素了
                    try {
                        //当前线程进入等待状态，并且释放Produce之前占有的list集合的锁
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //程序执行到这，说明仓库是空的，可以生产
                Object obj = new Object();
                list.add(obj);
                System.out.println(Thread.currentThread().getName() + "-->" + obj);
                //唤醒消费者进行消费
                list.notify();
            }
        }
    }
}

class Customer implements Runnable{
    private List list;
    public Customer(List list){
        this.list = list;
    }
    @Override
    public void run() {
        //一直消费
        while (true){
            synchronized (list){
                if(list.size() == 0){ //说明仓库中已经空了
                    try {
                        //当前线程进入等待状态，并且释放Customer之前占有的list集合的锁
                        list.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //程序执行到这，说明仓库是有数据的，进行消费
                Object obj = list.remove(0);
                System.out.println(Thread.currentThread().getName() + "-->" + obj);
                //唤醒生产者进行生产
                list.notify();
            }
        }

    }
}